﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using CartoGraphic.Model2;
using CartoGraphic.Util;

namespace CartoGraphic
{
    public partial class SimplifyForm : Form
    {
        public List<PolyLine> line1, line2;
        public List<SimplePoint> pointsS, pointsE;
        public List<Polygon> polygons, polygons2;
        Graphics g1, g2;
        int xmin=1000000, xmax=0, ymin=1000000, ymax=0;

        public int lengthX()
        {
            int xmin = 0, xmax = 0;
            foreach (Polygon geo in polygons)
            {
                int count = geo.PointArray.Count;
                for (int i = 0; i < count; i++)
                {
                    System.Drawing.Point point = (System.Drawing.Point)geo.PointArray[i];
                    if (point.X < xmin)
                        xmin = point.X;
                    if (point.X > xmax)
                        xmax = point.X;
                }
            }
            int X;
            X = xmax - xmin;
            return X;
        }

        public int lengthY()
        {
            int ymin = 0, ymax = 0;
            foreach (Polygon geo in polygons)
            {
                int count = geo.PointArray.Count;
                for (int i = 0; i < count; i++)
                {
                    System.Drawing.Point point = (System.Drawing.Point)geo.PointArray[i];
                    if (point.Y < ymin)
                        ymin = point.Y;
                    if (point.Y > ymax)
                        ymax = point.Y;
                }
            }
            int Y;
            Y = ymax - ymin;
            return Y;
        }

        public void iniRange()
        {
            foreach (Polygon geo in polygons)
            {
                int count = geo.PointArray.Count;
                for (int i = 0; i < count; i++)
                {
                    System.Drawing.Point point = (System.Drawing.Point)geo.PointArray[i];
                    if (point.Y < ymin)
                        ymin = point.Y;
                    if (point.Y > ymax)
                        ymax = point.Y;
                    if (point.X < xmin)
                        xmin = point.X;
                    if (point.X > xmax)
                        xmax = point.X;
                }
            }
        }

        public List<Polygon> newPolygons()
        {
            iniRange();
            double width = 1.0*(xmax - xmin)/3+0.1;
            double height = 1.0*(ymax - ymin)/3+0.1;
            //double lenX = lengthX() / 3.0;
            //double lenY = lengthY() / 3.0;
            int S = 0;

            List<Polygon>[][] ary = new List<Polygon>[3][];
            for (int i = 0; i < 3; i++)
            {
                ary[i] = new List<Polygon>[3];
                for (int j = 0; j < 3; j++)
                    ary[i][j] = new List<Polygon>();
            }

            foreach (Polygon geo in polygons)
            {
                geo.Area = area(geo);
                geo.Center = (System.Drawing.Point)geo.PointArray[0];
            }

            foreach (Polygon geo in polygons)
            {
                int count = geo.PointArray.Count;

                int m, n;
                double x, y;
                x = 1.0 * geo.Center.X;
                y = 1.0 * geo.Center.Y;
                m = (int)(1.0*(x-xmin) / width);
                n = (int)(1.0*(y-ymin) / height);
                ary[m][n].Add(geo);

            }

            List<Polygon> newPolygons = new List<Polygon>();

            int p = (int)(polygons.Count / 9);
            for (int m = 0; m < 3; m++)
            {
                for (int n = 0; n < 3; n++)
                {
                    if (true)
                    {
                        int q = (int)(1.0 * ary[m][n].Count / 2);
                        int i = 0;
                        foreach (Polygon geo in ary[m][n].OrderByDescending(x => x.Area))
                        {
                            newPolygons.Add(geo);
                            i++;
                            if (i == q)
                                break;
                        }
                        //ary[m][n].OrderByDescending(x => x.Area);
                        //for (int i = q; i < ary[m][n].Count; i++)
                        //{
                        //    newPolygons.Add(ary[m][n][i]);
                        //}
                    }
                    //else
                    //{
                    //    for (int i = 0; i < ary[m][n].Count; i++)
                    //    {
                    //        newPolygons.Add(ary[m][n][i]);
                    //    }
                    //}
                }
            }

            return newPolygons;
        }

        public void OrderByDecending(List<Polygon> polygons)
        {
 
        }

        public SimplifyForm()
        {
            InitializeComponent();
            g1 = splitContainer1.Panel1.CreateGraphics();
            g2 = splitContainer1.Panel2.CreateGraphics();
            line2 = new List<PolyLine>();
        }

        private void 线化简ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            foreach (PolyLine line in line1)
            {
                List<Util.Point> points = getPoints(line);
                List<Util.Point> afterPoints = Util.Utility.DouglasPeuckerReduction(points, 3);
                PolyLine lineafter = getPolyLine(afterPoints);
                line2.Add(lineafter);
            }
            foreach (PolyLine line in line1)
                line.Draw(g1, new GraphicsProperties(Color.Black, Color.White, 2, false));
            foreach (PolyLine line in line2)
            {
                if (line.PointArray.Count > 2)
                    line.Draw(g2, new GraphicsProperties(Color.Black, Color.White, 2, false));
            }

        }

        public List<Util.Point> getPoints(PolyLine line)
        {
            List<Util.Point> points = new List<Util.Point>();
            for (int i = 0; i < line.PointArray.Count; i++)
            {
                System.Drawing.Point point = (System.Drawing.Point)line.PointArray[i];
                points.Add(new Util.Point(point.X, point.Y));
            }
            return points;
        }

        public PolyLine getPolyLine(List<Util.Point> points)
        {
            PolyLine line = new PolyLine();
            foreach (Util.Point point in points)
            {
                System.Drawing.Point one = new System.Drawing.Point((int)point.X, (int)point.Y);
                line.AddPoint(one);
            }
            return line;
        }

        public double[][] getPosition(List<SimplePoint> points)
        {
            double[][] rawData = new double[points.Count][];
            for (int i = 0; i < points.Count; i++)
            {
                rawData[i] = new double[] { points[i].Center.X, points[i].Center.Y };
            }
            return rawData;
        }

        public List<SimplePoint> getPoints(double[][] Position)
        {
            List<SimplePoint> points = new List<SimplePoint>();
            for (int i = 0; i < Position.Length; i++)
            {
                System.Drawing.Point point = new System.Drawing.Point((int)(Position[i][0]), (int)(Position[i][1]));
                SimplePoint spoint = new SimplePoint(point, "");
                points.Add(spoint);
            }
            return points;
        }


        private void splitContainer1_Panel1_Paint(object sender, PaintEventArgs e)
        {

        }

        private void 点群选取ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            pointsE = new List<SimplePoint>();
            List<int> indexs = new List<int>();
            splitContainer1.Panel1.Refresh();
            double[][] positions = getPosition(pointsS);
            int[] clustering = KMeans.Cluster(positions, (int)(pointsS.Count * 0.3));

            for (int i = 0; i < clustering.Length; i++)
            {
                if (!indexs.Contains(clustering[i]))
                {
                    pointsE.Add(pointsS[i]);
                    indexs.Add(clustering[i]);
                }
            }
            foreach (SimplePoint point in pointsS)
            {
                point.Draw(g1, new GraphicsProperties(Color.Black, Color.White, 3, false));
            }
            foreach (SimplePoint point in pointsE)
            {
                point.Draw(g1, new GraphicsProperties(Color.Red, Color.White, 3, false));
            }
        }

        private double area(Polygon polygon)
        {
            double sum = 0;
            for (int i = 0; i < polygon.PointArray.Count - 1; i++)
            {
                System.Drawing.Point a = (System.Drawing.Point)polygon.PointArray[i];
                System.Drawing.Point b = (System.Drawing.Point)polygon.PointArray[i + 1];
                sum += -0.5 * (a.X * b.Y - b.X * a.Y);
            }
            //System.Drawing.Point a_s = (System.Drawing.Point)polygon.PointArray[0];
            //System.Drawing.Point b_e = (System.Drawing.Point)polygon.PointArray[polygon.PointArray.Count-1];
            //sum += -0.5 * (-a_s.X * b_e.Y + a_s.Y * b_e.X);
            return Math.Abs(sum);
        }

        private void 密度选取ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            polygons2 = newPolygons();
            foreach (Polygon geo in polygons)
                geo.Draw(g1, new GraphicsProperties(Color.Black, Color.White, 1, false));
            foreach (Polygon geo in polygons2)
                geo.Draw(g1, new GraphicsProperties(Color.Red, Color.White, 1, false));
        }
    }
}
